import { Service } from 'egg'
import { UserProps } from '../model/user'

export interface GiteeUserInfo {
  id: number
  name: string
  avatar_url: string
  email: string
}

export default class User extends Service {
  async createUser(payload: Partial<UserProps>) {
    const { ctx } = this
    const { password } = payload
    let userInfo: Partial<UserProps>
    if (password) {
      const passwordHash = await ctx.genHash(password)
      userInfo = {
        ...payload,
        password: passwordHash,
      }
    } else {
      userInfo = {
        ...payload,
      }
    }
    const res = await ctx.model.User.create(userInfo)
    return res
  }

  async getUserById(id: string) {
    const { ctx } = this
    const res = await ctx.model.User.findById(id)
    return res
  }

  async getUserByName(username: string) {
    const { ctx } = this
    const res = await ctx.model.User.findOne({ username })
    return res
  }

  async loginByCellphone(phoneNumber: string) {
    const { ctx } = this
    const user = await this.getUserByName(phoneNumber)
    if (user) {
      return ctx.helper.jwtUsername(user.username)
    }
    // 创建用户
    const newUserInfo: Partial<UserProps> = {
      username: phoneNumber,
      phoneNumber,
      type: 'cellphone',
    }
    const resUser = await this.createUser(newUserInfo)
    return ctx.helper.jwtUsername(resUser.username)
  }

  /**
   * 获取gitee OAuthToken
   * @param code 获取token的凭证
   */
  async getGiteeOAuthToken(code: string) {
    const { ctx, app } = this
    const { authUrl, client_id, client_secret, redictUrl } = app.config.giteeOAuthConfig
    const resp = await ctx.curl(authUrl, {
      method: 'POST',
      dataType: 'json',
      contentType: 'json',
      data: {
        code,
        client_id,
        client_secret,
        redirect_uri: redictUrl,
      },
    })
    app.logger.info('获取gitee OAuthToken =>', resp.data)
    return resp.data.access_token
  }

  async getGiteeOAuthUserInfo(accessToken: string) {
    const { ctx, app } = this
    const { userApiUrl } = app.config.giteeOAuthConfig
    const resp = await ctx.curl<GiteeUserInfo>(`${userApiUrl}?access_token=${accessToken}`, {
      dataType: 'json',
    })
    return resp.data
  }

  async loginByGiteeOAuth(code: string) {
    const { ctx } = this

    const accessToken = await this.getGiteeOAuthToken(code)
    const giteeUserInfo = await this.getGiteeOAuthUserInfo(accessToken)
    const userName = `gitee_${giteeUserInfo.id}`
    const user = await this.getUserByName(userName)
    if (user) {
      return ctx.helper.jwtUsername(user.username)
    }

    const newUserInfo: Partial<UserProps> = {
      username: userName,
      nickname: giteeUserInfo.name,
      type: 'oauth',
      provider: 'gitee',
      oauthID: giteeUserInfo.id.toString(),
      email: giteeUserInfo.email,
      picture: giteeUserInfo.avatar_url,
    }
    const resUser = await this.createUser(newUserInfo)
    return ctx.helper.jwtUsername(resUser.username)
  }
}
